/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.cvut.fel.taskpro.view.controller;

import cz.cvut.fel.taskpro.business.imanager.IGroupBusiness;
import cz.cvut.fel.taskpro.business.imanager.ISubjectBusiness;
import cz.cvut.fel.taskpro.business.imanager.IUserBusiness;
import cz.cvut.fel.taskpro.business.support.BusinessRuleException;
import cz.cvut.fel.taskpro.data.entity.GroupTaskPro;
import cz.cvut.fel.taskpro.data.entity.Kantor;
import cz.cvut.fel.taskpro.data.entity.Student;
import cz.cvut.fel.taskpro.data.entity.Subject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

/**
 * This controller is responsible for modify study group. Controller provide
 * operation as change kantor in study group, add or remove user from group and
 * remove group. Controller is view scope and is called as modifyGroupBean.
 *
 * @author Tom
 * @version 1.0.0. beta
 */
@ManagedBean(name = "modifyGroupBean")
@ViewScoped
public class ModifyGroupController extends AbstractController {

    private List<Subject> allSubjects;
    private Subject selectedSubject;
    private List<GroupTaskPro> groups;
    private GroupTaskPro selectedGroup;
    private List<Student> studentsInGroup;
    private List<Student> studentToAdd;
    private List<Kantor> kantorsToAdd;
    private Kantor selectedKantor;
    private Student[] selectedStudents;
    private List<Student> studentsToRemove;
    private boolean displayDetails;
    private boolean displayGroups;
    private boolean displaySubjects;
    private boolean naviSubject;
    private boolean naviGroup;
    private boolean back;
    private GroupTaskPro upadtedGroup;
    @EJB
    private ISubjectBusiness subjectB;
    @EJB
    private IGroupBusiness groupB;
    @EJB
    private IUserBusiness userB;

    /**
     * This method initialize class, load all subject in system and set up view
     * rendered variable.
     */
    @PostConstruct
    public void init() {
        recognizeLogin();
        displayDetails = false;
        displayGroups = false;
        displaySubjects = true;
        naviGroup = false;
        naviSubject = false;
        allSubjects = subjectB.showSubjects();
    }

    /**
     * This method ask business layer for load groups, which are part of
     * selected subject. Then modify view display variables.
     *
     */
    public void chooseSubject() {
        try {
            groups = groupB.getGroups(selectedSubject);
            naviSubject = true;
            displayDetails = false;
            displayGroups = true;
            displaySubjects = false;
            displaySubjects = false;
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
        }
    }

    /**
     * This method ask business layer for load all students who are in selected
     * group. Then reset updated group and set updated group as selected group.
     * Bean also modify view display variables.
     */
    public void chooseGroup() {
        try {
            studentsInGroup = userB.getStudentsByGroup(selectedGroup);
            upadtedGroup = new GroupTaskPro();
            upadtedGroup.setCode(selectedGroup.getCode());
            upadtedGroup.setKantor(selectedGroup.getKantor());
            upadtedGroup.setDayOfTeach(selectedGroup.getDayOfTeach());
            upadtedGroup.setStartTime(selectedGroup.getStartTime());
            upadtedGroup.setStopTime(selectedGroup.getStopTime());
            naviGroup = true;
            naviSubject = true;
            displayDetails = true;
            displayGroups = false;
            displaySubjects = false;
            back = false;
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
        }
    }

    /**
     * This method set view rendered variable as they are in selecting subject
     * dialog. This is necessary to back button wizzard.
     */
    public void toChooseSubject() {
        displayDetails = false;
        displayGroups = false;
        displaySubjects = true;
        naviGroup = false;
        naviSubject = false;
        back = true;
    }

    /**
     * This method set view rendered variable as they are in selecting group
     * dialog. This is necessary to back button wizzard.
     */
    public void toChooseGroup() {
        naviGroup = false;
        naviSubject = true;
        displayDetails = false;
        displayGroups = true;
        displaySubjects = false;
        back = true;
    }

    /**
     * This method set view rendered variable as they are in editing group
     * dialog. This is necessary to back button wizzard.
     */
    public void backToEdit() {
        naviGroup = true;
        naviSubject = true;
        displayDetails = true;
        displayGroups = false;
        displaySubjects = false;
        back = false;
    }

    /**
     * This method remove student from actual list and will be added to list of
     * students to future remove., but not from database. If student were
     * already removed then do nothing.
     *
     * @param studentToRemove students which will be removed from actual student
     * list and will be added to list of students to future remove.
     */
    public void removeStudents(Student studentToRemove) {
        studentsInGroup.remove(studentToRemove);
        if (studentsToRemove == null) {
            studentsToRemove = new ArrayList<Student>();
        }
        if (!studentsToRemove.contains(studentToRemove)) {
            studentsToRemove.add(studentToRemove);
        }
    }

    /**
     * This method modify selected group. Remove or add students, depend on
     * state of controller. For this all action is asked business layer.
     */
    public void modify() {
        try {
            upadtedGroup.setMStudents(studentsInGroup);
            upadtedGroup.setmAssignments(selectedGroup.getmAssignments());
            upadtedGroup.setmTeams(selectedGroup.getmTeams());
            upadtedGroup.setSubject(selectedGroup.getSubject());
            groupB.updateGroup(selectedGroup, upadtedGroup, studentsToRemove);
            printSuccMessage("Modify group: ", "The group " + upadtedGroup.getCode() + " in subject " + upadtedGroup.getSubject().getCode() + " has been successfully modify.");
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
        }
    }

    /**
     * This method ask business layer for load all studens in database.
     */
    public void loadStudents() {
        studentToAdd = userB.getStudentsAll();
    }

    /**
     * This method ask business layer for load all kantors in database.
     */
    public void loadKantorsToAdd() {
        kantorsToAdd = userB.getAllKantor();
    }

    /**
     * This method ask business layer for remove selected group. Then reset view
     * display variable.
     */
    public void removeGroup() {
        try {
            groupB.removeGroup(selectedGroup);
            upadtedGroup = null;
            displayDetails = false;
            displayGroups = true;
            displaySubjects = false;
            naviGroup = false;
            naviSubject = true;
            back = false;
            printSuccMessage("Removing group: ", "The group " + selectedGroup.getCode() + " in subject " + selectedGroup.getSubject().getCode() + " has been successfully removed.");
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
        }
    }

    /**
     * This method added selected students to group list, which can be future
     * added to database.
     */
    public void addStudentToGroup() {
        if (selectedStudents != null) {
            List<Student> students = Arrays.asList(selectedStudents);
            Iterator stIt = students.iterator();
            while (stIt.hasNext()) {
                Student currStudent = (Student) stIt.next();
                if (studentsInGroup.contains(currStudent)) {
                    printErrMessage("Addind student", "This student is already in this group.");
                    return;
                }
            }
            studentsInGroup.addAll(students);
            if (studentsToRemove != null) {
                List<Student> tempStudentToRemove = new ArrayList<Student>(studentsToRemove);
                Iterator stToremoveIt = tempStudentToRemove.iterator();
                while (stToremoveIt.hasNext()) {
                    Student studentToRemove = (Student) stToremoveIt.next();
                    if (studentsInGroup.contains(studentToRemove)) {
                        studentsToRemove.remove(studentToRemove);
                    }
                }
            }
        }
        selectedStudents = null;
    }

    /**
     * This method change kantor of group only localy in view and controller not
     * int database.
     */
    public void changeKantor() {
        upadtedGroup.setKantor(selectedKantor);
    }

    public List<Subject> getAllSubjects() {
        return allSubjects;
    }

    public void setAllSubjects(List<Subject> allSubjects) {
        this.allSubjects = allSubjects;
    }

    public List<GroupTaskPro> getGroups() {
        return groups;
    }

    public void setGroups(List<GroupTaskPro> groups) {
        this.groups = groups;
    }

    public GroupTaskPro getSelectedGroup() {
        return selectedGroup;
    }

    public void setSelectedGroup(GroupTaskPro selectedGroup) {
        this.selectedGroup = selectedGroup;
    }

    public Student[] getSelectedStudents() {
        return selectedStudents;
    }

    public void setSelectedStudents(Student[] selectedStudents) {
        this.selectedStudents = selectedStudents;
    }

    public Subject getSelectedSubject() {
        return selectedSubject;
    }

    public void setSelectedSubject(Subject selectedSubject) {
        this.selectedSubject = selectedSubject;
    }

    public List<Student> getStudentsInGroup() {
        return studentsInGroup;
    }

    public void setStudentsInGroup(List<Student> studentsInGroup) {
        this.studentsInGroup = studentsInGroup;
    }

    public boolean isDisplayDetails() {
        return displayDetails;
    }

    public void setDisplayDetails(boolean displayDetails) {
        this.displayDetails = displayDetails;
    }

    public boolean isDisplayGroups() {
        return displayGroups;
    }

    public void setDisplayGroups(boolean displayGroups) {
        this.displayGroups = displayGroups;
    }

    public boolean isDisplaySubjects() {
        return displaySubjects;
    }

    public void setDisplaySubjects(boolean displaySubjects) {
        this.displaySubjects = displaySubjects;
    }

    public boolean isNaviGroup() {
        return naviGroup;
    }

    public void setNaviGroup(boolean naviGroup) {
        this.naviGroup = naviGroup;
    }

    public boolean isNaviSubject() {
        return naviSubject;
    }

    public void setNaviSubject(boolean naviSubject) {
        this.naviSubject = naviSubject;
    }

    public boolean isBack() {
        return back;
    }

    public void setBack(boolean back) {
        this.back = back;
    }

    public GroupTaskPro getUpadtedGroup() {
        return upadtedGroup;
    }

    public void setUpadtedGroup(GroupTaskPro upadtedGroup) {
        this.upadtedGroup = upadtedGroup;
    }

    public List<Student> getStudentToAdd() {
        return studentToAdd;
    }

    public void setStudentToAdd(List<Student> studentToAdd) {
        this.studentToAdd = studentToAdd;
    }

    public List<Kantor> getKantorsToAdd() {
        return kantorsToAdd;
    }

    public void setKantorsToAdd(List<Kantor> kantorsToAdd) {
        this.kantorsToAdd = kantorsToAdd;
    }

    public Kantor getSelectedKantor() {
        return selectedKantor;
    }

    public void setSelectedKantor(Kantor selectedKantor) {
        this.selectedKantor = selectedKantor;
    }
}
